#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "nvs_flash.h"
#include "esp_vfs_fat.h"

#include "audio_event_iface.h"

#include "esp_peripherals.h"
#include "periph_wifi.h"
#include "periph_sdcard.h"
#include "periph_touch.h"
#include "board.h"
#include "ftp_server.h"
// #include "tftp_disk.h"

#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD

static const char *TAG = "wifi_flash_disk";

static void main_task(void *pvParameters)
{
    // deep_sleep_timer = xTimerCreate("deep sleep timeout timer", 100000/portTICK_PERIOD_MS, pdFALSE, NULL, deep_sleep_timer_cback);
    // xTimerStart(deep_sleep_timer, portMAX_DELAY);

    esp_periph_config_t periph_cfg = {0};
    esp_periph_init(&periph_cfg);
    periph_sdcard_cfg_t sdcard_cfg = {
        .root = "/sdcard",
        .card_detect_pin = SD_CARD_INTR_GPIO,
    };
    esp_periph_handle_t sdcard_handle = periph_sdcard_init(&sdcard_cfg);
    esp_periph_start(sdcard_handle);
    while(!periph_sdcard_is_mounted(sdcard_handle)) {
        vTaskDelay(100/portTICK_PERIOD_MS);
    }

    struct dirent *p_dirent;
    DIR *p_dir;
    p_dir = opendir("/sdcard");
    if(p_dir != NULL) {
        while(NULL != (p_dirent = readdir(p_dir))) {
            if(p_dirent->d_type == DT_REG) {
                ESP_LOGI(TAG, "file: %s", p_dirent->d_name);
            }else {
                ESP_LOGI(TAG, "dir %s", p_dirent->d_name);
            }
        }
    }
    FILE *file;
    file = fopen("/sdcard/readme.txt", "r");
    if(!file) {
        ESP_LOGI(TAG, "open file ERR!!!");
    }
    else
    {
        char buf[50];
        int len = fread(buf, 1, 50, file);
        if(len > 0) {
            ESP_LOGI(TAG, "%s", buf);
        }
    }
    fclose(file);

    periph_wifi_cfg_t wifi_cfg = {
        .ssid = EXAMPLE_WIFI_SSID,
        .password = EXAMPLE_WIFI_PASS,
        .max_connection = 5,
        .authmode = WIFI_AUTH_WPA_WPA2_PSK,
    };
    tcpip_adapter_init();
    esp_periph_handle_t wifi_handle = periph_wifi_init(&wifi_cfg);
    esp_periph_start(wifi_handle);

    audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
    audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg); 
    audio_event_iface_set_listener(esp_periph_get_event_iface(), evt);
    while(1) {
        audio_event_iface_msg_t msg;
        esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
        if(ret != ESP_OK) {
            continue;
        }
        if(msg.source_type == PERIPH_ID_WIFI && msg.source == (void *)wifi_handle) {
            if(msg.cmd == PERIPH_WIFI_STACONNECTED) {
                ftp_server_init();
                ESP_LOGI(TAG, "wifi sta connected...");
            }
            else if(msg.cmd == PERIPH_WIFI_STADISCONNECTED) {
                ESP_LOGI(TAG, "wifi sta disconnected...");
            }
        }
        if(msg.source_type == PERIPH_ID_TOUCH) {
            ESP_LOGI(TAG, "touch event...");
        }
        if(msg.source_type == PERIPH_ID_SDCARD) {
            ESP_LOGI(TAG, "sdcard event...");
        }
    }
    esp_periph_stop_all();
    audio_event_iface_remove_listener(esp_periph_get_event_iface(), evt);
    audio_event_iface_destroy(evt);
    esp_periph_destroy();
    vTaskDelete(NULL);
}

static void heap_check_task(void *pvParameters)
{
    while(1){
        vTaskDelay(5000/portTICK_RATE_MS);
        char *pcWriteBuffer = malloc(500);
        vTaskList(pcWriteBuffer);
        ESP_LOGI(TAG, "\ntask_name    task_state     priority          statck           task_num\n%s\n", pcWriteBuffer);
        vTaskGetRunTimeStats(pcWriteBuffer);
        ESP_LOGI(TAG, "\ntask_name        RunTimeCounter         StatsAsPercentage\n%s\n", pcWriteBuffer);
        free(pcWriteBuffer);
    }
}

void app_main()
{
    ESP_ERROR_CHECK( nvs_flash_init() );
    xTaskCreate(&main_task, "m_task", 4096, NULL, 5, NULL);
    xTaskCreate(&heap_check_task, "h_task", 2000, NULL, 2, NULL);
}
